﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using SpectationClient.GUI;
using SpectationClient.Stuff;
using SpectationClient.SQLCommandBuilder;
using Npgsql;
using SpectationClient.DataBaseDescription;

namespace SpectationClient
{
    public partial class SPECTATION_Client : Form
    {
        private NpgsqlConnection con = null;
        //private string cstring = null;
        private DBManager dbm = null;
        private BackgroundWorker BGW_initDBM = null;

        private List<ToolStripMenuItem> needConnection = new List<ToolStripMenuItem>();


        public SPECTATION_Client(){
            InitializeComponent();
            this.Icon = Resources.Icon;
            this.Text = String.Format("{0}", Application.ProductName);

            needConnection.Add(tsmiSearch);
            needConnection.Add(tsmiInsert);
            needConnection.Add(tsmiToolsShowDBTables);
            needConnection.Add(tsmiToolsSQLConsole);
            needConnection.ForEach(i => i.Enabled = false);

            BGW_initDBM = new BackgroundWorker();
            BGW_initDBM.WorkerSupportsCancellation = true;
            BGW_initDBM.WorkerReportsProgress = true;
            BGW_initDBM.DoWork += new DoWorkEventHandler(BGW_initDBM_DoWork);
            BGW_initDBM.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BGW_initDBM_RunWorkerCompleted);
            BGW_initDBM.ProgressChanged += new ProgressChangedEventHandler(BGW_initDBM_ProgressChanged);
            #if DEBUG
                NpgsqlConnectionStringBuilder csb = new NpgsqlConnectionStringBuilder();
                csb.Host = "localhost";
                   
                csb.Database = "SPECLIB";
                csb.Password = "speclib";
                csb.UserName = "SPECLIB_Viewer";
               
                csb.Add("COMMANDTIMEOUT", 30);// Properties.Settings.Default.DEF_COMMAND_TIMEOUT);
                csb.Add("TIMEOUT", 30);//Properties.Settings.Default.DEF_CONNECTION_TIMEOUT);
                csb.Add("CONNECTIONLIFETIME", 2);
                this.con = new NpgsqlConnection(csb.ConnectionString);
               
                //Stuff.Sandbox SBox = new global::SPECTATION_Client.Stuff.Sandbox(this.con);

                this.Cursor = Cursors.WaitCursor;
                BGW_initDBM.RunWorkerAsync(this.con.Clone());
               
            #endif
        }

        void BGW_initDBM_ProgressChanged(object sender, ProgressChangedEventArgs e) {
            
        }

        void BGW_initDBM_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
            this.Cursor = Cursors.Default;
            if(e.Cancelled == false && e.Result != null && e.Result.GetType() == typeof(DBManager)) {
                this.dbm = (DBManager)e.Result;

                needConnection.ForEach(i => i.Enabled = true);
               

            } else {
               needConnection.ForEach(i => i.Enabled = false);
            }
            
            this.con.ClearPool();
            this.con.Close();
        }

        /// <summary>
        /// Registerst informations to be shown elsewhere...
        /// </summary>
        /// <param name="info"></param>
        void dbm_InfoStreamEvent(string info) {
            Console.WriteLine(info);
        }

        
        void BGW_initDBM_DoWork(object sender, DoWorkEventArgs e) {
            BackgroundWorker meself = (BackgroundWorker)sender;
            try {
                NpgsqlConnection con = (NpgsqlConnection)e.Argument;
                DBManager dbm = new DBManager(con);
                e.Result = dbm;
                Thread checkVersionThread = new Thread(new ParameterizedThreadStart(checkClientVersion));
                checkVersionThread.Start(con);
            } catch(Exception ex) {
                e.Cancel = true;
                meself.CancelAsync();
                MessageBox.Show(TextHelper.Exception2String(ex), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            } finally {
                con.ClearPool();
                con.Close();
            }
        }

        private static void checkClientVersion(Object connectionObject) {
            //check client version
            if(connectionObject != null) {
                NpgsqlConnection con = (NpgsqlConnection)connectionObject;
                
                try {
                    NpgsqlCommand cmd = new NpgsqlCommand(
                        String.Format("SELECT * FROM {0} WHERE TYPE = 'SPECLIB_Client'",
                        Properties.Settings.Default.DEF_TABLE_CLIENTVERSION), con);
                    DataTable result = new DataTable();
                    con.Open();
                    NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd);
                    da.Fill(result);
                    String version_db = String.Format("{0}.{1:00}", result.Rows[0]["version_major"], result.Rows[0]["version_minor"]);
                    String version_my = String.Format("{0}.{1:00}", Properties.Settings.Default.CLIENT_VERSION_MAJOR, Properties.Settings.Default.CLIENT_VERSION_MINOR);
                    double v_db = Convert.ToInt16(result.Rows[0]["version_major"])*10 + Convert.ToInt16(result.Rows[0]["version_minor"]);
                    double v_my = Properties.Settings.Default.CLIENT_VERSION_MAJOR * 10 + Properties.Settings.Default.CLIENT_VERSION_MINOR;
                    if(v_my < v_db) {
                        MessageBox.Show(
                            String.Format("Diese Version ({0}) des SPECLIB_Clients ist veraltet.\n" +
                                          "Bitte nutzen Sie die aktuelle Version {1}", version_my, version_db),
                                          "Hinweis", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    } else {
                        Console.WriteLine("Client Version ({0}) is up-to-date", version_my);
                    }
                  
                } catch(Exception ex) {
                  
                   Console.WriteLine("Error during Version-Check \n"+TextHelper.Exception2String(ex));
                } finally {
                    con.ClearPool();
                    con.Close();
                    //String stop = "";
                }
            }
        }

        private void tslConnect_Click(object sender, EventArgs e){
            try {
               
                DBConnection dbc = new DBConnection();
                if(dbc.ShowDialog() == DialogResult.OK) {
                    try {

                        this.con = new NpgsqlConnection(dbc.ConnectionString);
                       
                        this.Cursor = Cursors.WaitCursor;
                        BGW_initDBM.RunWorkerAsync(this.con);
                    } catch(Exception ex) {
                        MessageBox.Show(TextHelper.Exception2String(ex), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }

                }
            } catch(Exception ex) {
                FormHelper.ShowErrorBox(ex);
            }
        }


        private void tsmiShow_Click(object sender, EventArgs e) {
            try{
                SubShowTables st = new SubShowTables(ref dbm);
                st.Show(this);
            } catch(Exception ex) {
                FormHelper.ShowErrorBox(ex);
            }
        }

        private void einzelnerSensorToolStripMenuItem_Click(object sender, EventArgs e) {
            try{
                SubInsertBaseInfo S = new SubInsertBaseInfo(ref dbm);
                S.Show(this);
            } catch(Exception ex) {
                FormHelper.ShowErrorBox(ex);
            }
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e) {
            try{
            if (con == null) {
                    MessageBox.Show("Bitte spezifizieren Sie die Verbindungseinstellungen zur Datenbank", "Hinweis", MessageBoxButtons.OK, MessageBoxIcon.Information);
                } else {
                    SubSearch ss = new SubSearch(ref dbm);
                    ss.Show(this);
                }
            } catch(Exception ex) {
                FormHelper.ShowErrorBox(ex);
            }
        }

        private void sucheInTabelleCORESPECTRAToolStripMenuItem_Click(object sender, EventArgs e) {
            try {
                SubShowSelectionTable SS = new SubShowSelectionTable(ref dbm, "CORE", "SPECTRA", true, false, "Suche über CORE.SPECTRA: bitte Auswahl vornehmen", "Auswahl übernehmen");
                SS.ResultOK_hasSelection += new EventHandler(SS_ResultOK_hasSelection);
                SS.Show(this);
            } catch (Exception ex) {
                FormHelper.ShowErrorBox(ex);
            }
        }

        void SS_ResultOK_hasSelection(object sender, EventArgs e) {
            SubShowSelectionTable SS = (SubShowSelectionTable)sender;
            TableInfo ti = SS.TableInfo;
            List<Object[]> idList = SS.getSelectedIDs();

            ConditionList cl = new ConditionList(ConditionList.Op.OR);
            cl.AddIDs(ti.PrimaryKey.Names, idList);
            try {
                NpgsqlCommand cmd = cl.getCmd();
                cmd.CommandText = String.Format("SELECT * FROM {0} WHERE {1}",
                        this.dbm.getDataBaseInfo()["CORE"]["SPECTRA"].SchemaTableName, cmd.CommandText );

                SubSearchResults SSR = new SubSearchResults(cmd, this.dbm);
                SSR.Show();
            } finally { }
            //spectraIDs aus selection übernehmen
            //neue Anfrage stellen
             
        }


        private void fotosHinzufügenToolStripMenuItem_Click(object sender, EventArgs e) {
            try {
                SubInsertGFZPhotos S = new SubInsertGFZPhotos(ref dbm);
                S.Show(this);
            } catch(Exception ex) {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }


        private void sucheInTabelleCGFZOBSERVATIONAREASToolStripMenuItem_Click(object sender, EventArgs e){
            try {
                SubShowSelectionTable SS_ObsArea = new SubShowSelectionTable(ref dbm, "C_GFZ", "VIEW_OBSERVATION_AREAS", true, false, "Suche über C_GFZ.OBSERVATION_AREAS: Gebiet auswählen", "Auswahl übernehmen");
                SS_ObsArea.ResultOK_hasSelection += new EventHandler(SS_ObsArea_ResultOK_hasSelection);
                SS_ObsArea.Show(this);
            } catch(Exception ex) {
                MessageBox.Show(ex.Message);
            }
        }

        void SS_ObsArea_ResultOK_hasSelection(object sender, EventArgs e) {
            SubShowSelectionTable SS = (SubShowSelectionTable)sender;
            
            TableInfo ti_spec = dbm.getTableInfo("CORE", "SPECTRA");
            TableInfo ti_obs_view = dbm.getTableInfo("C_GFZ", "VIEW_SPEC2OBSERVATION_AREAS");

            ConditionList cl = new ConditionList(ConditionList.Op.OR);
            cl.AddIDs(new String[]{"id"}, SS.getSelectedValues(new String[]{"id"}));
            NpgsqlCommand cmd = cl.getCmd();
            cmd.CommandText = 
               String.Format("SELECT * FROM {0} WHERE id in (SELECT id_spectrum AS id FROM {1} WHERE {2})", 
                        ti_spec.SchemaTableName, ti_obs_view.SchemaTableName, cmd.CommandText);
            try {
                SubSearchResults SSR = new SubSearchResults(cmd, this.dbm);
               SSR.Show();
            } finally { }
        }

        private void tsmiAbout_Click(object sender, EventArgs e) {
            new SpectationClientInfo().ShowDialog();
        }

        private void tsmiDBSchema_Click(object sender, EventArgs e) {
            string path = String.Format(@"{0}\{1}\{2}", 
                Application.StartupPath,
                Properties.Settings.Default.DIR_DOCUMENTS,
                Properties.Settings.Default.FN_DB_SCHEMA_PDF);
            DataHelper.openFile(path);
            
        }

        private void observationsgebietToolStripMenuItem_Click(object sender, EventArgs e) {
            try {
                SubInsertObservationArea SIO = new SubInsertObservationArea(ref this.dbm);
                SIO.Show();
                
            } catch(Exception ex) {
                MessageBox.Show(TextHelper.Exception2String(ex), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void gesamtesProtokollToolStripMenuItem_Click(object sender, EventArgs e) {
            try {
                SubInsertMessprotokollGFZ MP = new SubInsertMessprotokollGFZ(ref this.dbm);
                MP.Show();

            } catch(Exception ex) {
                MessageBox.Show(TextHelper.Exception2String(ex), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void SPECLIB_Client_FormClosed(object sender, FormClosedEventArgs e) {
            //String temp = "";
            this.Dispose();
        }

        private void tsmiManual_Click(object sender, EventArgs e) {
            string path = String.Format(@"{0}\{1}\{2}", 
                Application.StartupPath,
                Properties.Settings.Default.DIR_DOCUMENTS,
                Properties.Settings.Default.FN_MANUAL_PDF);
            DataHelper.openFile(path);
        }

        private void tsmi_SQLConsole_Click(object sender, EventArgs e) {
            SubCommandLine SCL = new SubCommandLine(this.dbm);
            SCL.Show();
        }

        private void spektraldateienÖffnenToolStripMenuItem_Click(object sender, EventArgs e) {
            try {
                Process p = new Process();
                p.StartInfo.FileName = "SpectralViewer.exe";
                p.Start();
            } catch(Exception ex) {
                FormHelper.ShowErrorBox(ex);
            }
        }

        private void infoÜberSPECTATIONClientToolStripMenuItem_Click(object sender, EventArgs e) {
            (new SpectationClientInfo()).ShowDialog(); 
        }

    


    }
}
